/*
 * The RavenX Library
 * Copyright (c) 2008 by Solidus
 * 
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.It is provided "as is" without express 
 * or implied warranty.
 *
 */
#include "rx_mem.h"
#include "rx_debug.h"
#include <memory.h>
#include <string.h>
#include <stdlib.h>

RX_SPACE_BEG










void* rx_memcpy(void *dest, const void *src, size_t count)
{
		RX_ASSERT(dest != NULL);
		
		return memcpy(dest, src, count);
}

rx_wchar* rx_wmemcpy(rx_wchar *dest, const rx_wchar *sour, size_t count)
{
		return (rx_wchar*)rx_memcpy(dest, sour, count * sizeof(rx_wchar));
}




void* rx_memmove(void *dest, const void *src, size_t count)
{
		RX_ASSERT(dest != NULL);
		RX_ASSERT(src != NULL);
		return memmove(dest, src, count);
}

rx_wchar* rx_wmemmove(rx_wchar *dest, const rx_wchar *src, size_t count)
{
		RX_ASSERT(dest != NULL && src != NULL);
		return (rx_wchar*)rx_memmove(dest, src, count * sizeof(rx_wchar));

}

void* rx_memset(void *dest, int c, size_t count)
{
		RX_ASSERT(dest != NULL);
		return memset(dest, c, count);
}

rx_wchar* rx_wmemset(rx_wchar *dest, rx_wchar c, size_t count)
{
		size_t i;
		rx_wchar *ptr = dest;

		RX_ASSERT(dest != NULL);
		
		for(i = 0; i < count; ++i)*ptr++ = c;
		
		return dest;
}




void* rx_memfill(void* dst, const void* value, size_t count, size_t element_size)
{
		RX_ASSERT(dst != NULL && value != NULL && element_size > 0);

		if(element_size == sizeof(rx_byte))
		{
				return rx_memset(dst, *(const rx_byte*)value, count);
		}else if(element_size == sizeof(rx_wchar))
		{
				return rx_wmemset((rx_wchar*)dst, *(rx_wchar*)value, count); 
		}else
		{
				rx_byte *ptr = (rx_byte*)dst;
				size_t	i = 0;

				while(i < count)
				{
						rx_memcpy(ptr, value, element_size);
						ptr += element_size;
						i++;
				}
				return dst;
		}
}

void rx_memswap(void* left, void* right, size_t size)
{
		rx_byte tmp;
		rx_byte *lptr, *rptr;
		size_t	i;

		RX_ASSERT(left != NULL && right != NULL);

		lptr = (rx_byte*)left;
		rptr = (rx_byte*)right;
		
		for(i = 0; i < size; ++i, ++lptr, ++rptr)
		{
				tmp = *lptr;
				*lptr = *rptr;
				*rptr = tmp;
		}
		


}


void rx_memreverse(void* sour, size_t count, size_t element_size)
{
		rx_byte *front = (rx_byte*)sour;
		rx_byte *back = (rx_byte*)sour + (count - 1)*element_size;
		size_t swap_count;
		RX_ASSERT(sour != NULL && element_size > 0 && count > 0);
		
		for(swap_count = count / 2; swap_count > 0; --swap_count)
		{
				rx_memswap(front, back, element_size);
				front += element_size;
				back -= element_size;
		}

}



int rx_memcmp(const void *l, const void *r, size_t size)
{
		return memcmp(l,r, size);
}


















/****************************************************default_alloctor*************************************************************************************************/







RX_INLINE static void* __def_malloc(size_t bytes, void *ctx)
{
		ctx = ctx;
		RX_ASSERT(ctx == NULL);
		
		return malloc(bytes);
}

RX_INLINE static void* __def_realloc(void* ptr, size_t bytes, void *ctx)
{
		ctx = ctx;
		RX_ASSERT(ctx == NULL);
		return realloc(ptr, bytes);
}

RX_INLINE static void __def_free(void* ptr, void *ctx)
{
		ctx = ctx;
		RX_ASSERT(ctx == NULL);
		free(ptr);
}


static rx_alloc_t __def_mem_alloctor = {__def_malloc, __def_realloc,__def_free, NULL};


const rx_alloc_t* rx_mem_default_alloctor()
{
		return &__def_mem_alloctor;

}

void rx_mem_set_default_alloctor(const rx_alloc_t *palloc)
{
		if(palloc == NULL)return;

		RX_ASSERT(palloc->alloc_f != NULL && palloc->dealloc_f != NULL && palloc->realloc_f != NULL);

		__def_mem_alloctor = *palloc;

}


void* rx_malloc(size_t size)
{
		return rx_mem_default_alloctor()->alloc_f(size, rx_mem_default_alloctor()->ctx);
}

void* rx_realloc(void *ptr, size_t size)
{
		return rx_mem_default_alloctor()->realloc_f(ptr, size, rx_mem_default_alloctor()->ctx);
}


void* rx_calloc(size_t num, size_t item_size)
{
		void *ptr = rx_malloc(num * item_size);
		return rx_memset(ptr, 0, num *item_size);
}

void	rx_free(void *ptr)
{
		rx_mem_default_alloctor()->dealloc_f(ptr, rx_mem_default_alloctor()->ctx);
}



RX_SPACE_END

